﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading;
using System.Windows;

namespace Uinside.CreditSystem.WPF.ViewModels
{
    /// <summary>
    /// A class of base class of all viewModels.
    /// </summary>
    public  abstract partial class ViewModelBase : INotifyPropertyChanged, IDisposable
    {
        #region View

        public virtual UIElement View { get; set; }

        #endregion

        #region Implementation of INotifyPropertyChanged

        protected bool SetField<T>(ref T field, T value, string propertyName)
        {
            if (EqualityComparer<T>.Default.Equals(field, value)) return false;
            field = value;
            OnPropertyChanged(propertyName);
            return true;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }

        /// <summary>
        /// KFGJFDKLKGJ
        /// </summary>
        /// <param name="args"></param>
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
        {
            //this code can be very safe for multiple-threads
            //http://
            PropertyChangedEventHandler result = Interlocked.CompareExchange(ref PropertyChanged, null, null);
            if (result != null)
                result(this, args);
        }

        #endregion

        #region CommonBackgroundWorker

        /// <summary>
        /// Wrapper one backgroundworker to execute some long-time operations
        /// </summary>
        /// <param name="workFunction">Work</param>
        /// <param name="completedCallback">Callback handler</param>
        protected static void RunBackgroundWorker(DoWorkEventHandler workFunction,
                                                  RunWorkerCompletedEventHandler completedCallback)
        {
            var worker = new BackgroundWorker();
            worker.DoWork += workFunction;
            worker.RunWorkerAsync();
            worker.RunWorkerCompleted += (sender, args) =>
                {
                    completedCallback(sender, args);
                    if (args.Error != null)
                        throw args.Error;
                };
        }

        ///// <summary>
        ///// Wrapper one backgroundworker to execute some long-time operations
        ///// </summary>
        ///// <param name="workFunction">Work</param>
        ///// <param name="completedCallback">Callback handler</param>
        //protected static void RunBackgroundWorker(DoWorkEventHandler workFunction,
        //                                          RunWorkerCompletedEventHandler completedCallback, object Argument)
        //{
        //    var worker = new BackgroundWorker();
        //    worker.DoWork += workFunction;
        //    worker.RunWorkerAsync(Argument);
        //    worker.RunWorkerCompleted += completedCallback;
        //}

        #endregion

        #region SetBusyState

        private string _busyContent = "载入中，请稍后..";

        private bool _isBusy;

        public string BusyContent
        {
            get { return _busyContent; }
            set
            {
                _busyContent = value;
                OnPropertyChanged("BusyContent");
            }
        }

        public bool IsBusy
        {
            get { return _isBusy; }
            set
            {
                _isBusy = value;
                OnPropertyChanged("IsBusy");
            }
        }

        /// <summary>
        ///     Sets the busy state to busy or not busy.
        /// </summary>
        /// <param name="busy">
        ///     if set to <c>true</c> the application is now busy.
        /// </param>
        protected void SetBusyState(bool busy)
        {
            if (busy == IsBusy) return;
            IsBusy = busy;
        }

        #endregion

        #region Implement IDisposable

        public virtual void Dispose()
        {
            View = null;
        }

        #endregion
    }
}